package com.nexus.all.controller;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.nexus.all.config.SpringParameterConfig;
import com.nexus.all.constants.RedisKeyNexus;
import com.nexus.all.dto.LoginBodyDTO;
import com.nexus.all.model.User;
import com.nexus.all.service.UserService;
import com.nexus.bean.annotation.PassLogin;
import com.nexus.bean.annotation.valid.AddGroup;
import com.nexus.bean.annotation.valid.OtherGroup;
import com.nexus.bean.constants.RedisKeyUser;
import com.nexus.bean.enums.LimitTypeEnums;
import com.nexus.bean.model.UserInfoVO;
import com.nexus.bean.result.Result;
import com.nexus.bean.result.ResultCode;
import com.nexus.bean.utils.StringUtils;
import com.nexus.bean.utils.UuIdUtils;
import com.nexus.bean.utils.ip.IpUtil;
//import com.nexus.redis.annotation.RateLimiter;
import com.nexus.redis.utils.RedisUtil;
import com.nexus.redis.utils.UserUtil;
import com.nexus.sms.dto.SmsSendApiDTO;
import com.nexus.sms.service.ISmsService;
import com.nexus.web.controller.CommonController;
import com.wf.captcha.ArithmeticCaptcha;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@RequestMapping("/login")
@RestController
@Api(tags = "用户登录管理接口")
@AllArgsConstructor
public class LoginController extends CommonController {


    private final UserService userService;
    private final ISmsService smsService;
    private final SpringParameterConfig springParameterConfig;


    @ApiOperation(value = "获取验证码", notes = "获取验证码")
    @GetMapping("/captcha/code")
    @PassLogin
    //@RateLimiter(count = 5, time = 60, limitType = LimitTypeEnums.IP)
    public Result code() {
        Map<String, String> data = new HashMap<>();
        String uuid = UuIdUtils.randomUUID(Boolean.TRUE);
        ArithmeticCaptcha captcha = new ArithmeticCaptcha(120, 40);
        // 获取运算的公式
        captcha.getArithmeticString();
        // 获取运算的结果
        String text = captcha.text();
        data.put("uuid", uuid);
        data.put("img", captcha.toBase64());
        // 验证码结果放到缓存中，30分钟有效
        RedisUtil.set(RedisKeyUser.getCodeKey(uuid), text, TimeUnit.MINUTES, 30);
        return Result.newSuccess(data);
    }

    @ApiOperation(value = "用户登录", notes = "用户登录")
    @PostMapping("/login")
    @PassLogin
    public Result login(@Validated(AddGroup.class) @RequestBody LoginBodyDTO dto) {
        if (springParameterConfig.getEnableCaptcha()) {
            // 验证码
            if (StringUtils.isBlank(dto.getUuid()) || StringUtils.isBlank(dto.getCode())) {
                return Result.newError(ResultCode.CAPTCHA_ERROR);
            }
            String codeKey = RedisKeyUser.getCodeKey(dto.getUuid());
            Object codeObject = RedisUtil.get(codeKey);
            if (codeObject == null) {
                return Result.newError(ResultCode.CAPTCHA_ERROR);
            }
            if (!dto.getCode().equals(codeObject.toString())) {
                return Result.newError(ResultCode.CAPTCHA_ERROR);
            }
            RedisUtil.delete(codeKey);
        }
        // 生成令牌
        UserInfoVO userInfoVO = userService.login(dto);

        //更新登录ip和登录时间
        User user = new User();
        user.setId(userInfoVO.getId());
        user.setLoginDate(LocalDateTime.now());
        user.setLoginIp(IpUtil.getIp(getRequest()));
        userService.updateById(user);

        UserUtil.setRedisUser(userInfoVO);
        return Result.newSuccess(userInfoVO.getToken());
    }

    @ApiOperation(value = "获取手机验证码", notes = "获取手机验证码")
    @GetMapping("sendCaptcha/{mobile}")
    @PassLogin
    //@RateLimiter(count = 1, time = 60, limitType = LimitTypeEnums.IP)
    public Result addCart(@ApiParam("手机号") @PathVariable String mobile) {
        //随机生成6位验证码
        String captchaCode = RandomUtil.randomNumbers(6);
        SmsSendApiDTO captchaDTO = buildCaptchaSmsDTO(mobile, captchaCode);
        smsService.sendCommonMessage(captchaDTO);
        //验证码存储redis
        RedisUtil.set(RedisKeyNexus.getMobileCaptchaKey(mobile), captchaCode, TimeUnit.SECONDS, 300);
        return Result.newSuccess();
    }

    private SmsSendApiDTO buildCaptchaSmsDTO(String mobile, String captchaCode) {
        SmsSendApiDTO sendApiDTO = new SmsSendApiDTO();
        sendApiDTO.setMobile(mobile);
        sendApiDTO.setSignName(springParameterConfig.getCaptchaSingName());
        sendApiDTO.setTemplateCode(springParameterConfig.getCaptchaTemplateCode());
        HashMap<String, Object> map = new HashMap<>();
        map.put("code", captchaCode);
        sendApiDTO.setTemplateParam(JSON.toJSONString(map));
        return sendApiDTO;
    }

    @ApiOperation(value = "手机号登录", notes = "手机号登录")
    @PostMapping("/mobileLogin")
    @PassLogin
    public Result<String> mobileLogin(@Validated(OtherGroup.class) @RequestBody LoginBodyDTO dto) {
        UserInfoVO userInfoVO = userService.mobileLogin(dto);
        //删除验证码
        RedisUtil.delete(RedisKeyNexus.getMobileCaptchaKey(dto.getUsername()));
        //更新登录ip和登录时间
        User user = new User();
        user.setId(userInfoVO.getId());
        user.setLoginDate(LocalDateTime.now());
        user.setLoginIp(IpUtil.getIp(getRequest()));
        userService.updateById(user);
        UserUtil.setRedisUser(userInfoVO);
        return Result.newSuccess(userInfoVO.getToken());
    }
}
